#include "GLMath3DApplication.h"
#include "GLRenderingContext.h"
using namespace OpenGLWrapper;

GLMath3DApplication::GLMath3DApplication()
	: GLApplication()
{
	_halfY = 0;
	_halfX = 0;
	_halfZ = 0;
	_stepX = 0;
	_stepY = 0;
	_stepZ = 0;
	_defInc = 0.01;
	_incX = 1;
	_incY = 1;
	_incZ = 1;
}

GLMath3DApplication::~GLMath3DApplication()
{

}

bool GLMath3DApplication::Init()
{
	if (!GLApplication::Init())
		return false;


	return true;
}
void GLMath3DApplication::Prepare(float dt)
{
	GLApplication::Prepare(dt);


}

void GLMath3DApplication::Render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glScaled(_scaleValue, _scaleValue, 1.0);
	glTranslatef(_translateX, _translateY, _translateZ);
	glRotatef(_rotationX, 1.0f, 0.0f, 0.0f);
	glRotatef(_rotationY, 0.0f, 1.0f, 0.0f);
	glRotatef(_rotationZ, 0.0f, 0.0f, 1.0f);
	_fontSize = _defaultFontSize / _scaleValue;

	auto renderingContext = GLRenderingContext::GetCurrentContext();
	glColor3d(1.0, 1.0, 1.0);
	for (int i = -_stepY; i > -_halfY; i -= _stepY)
	{
		char str3D[1024];
		sprintf_s(str3D, "%g", (i / (float)_stepY) * _incY);
		renderingContext->RenderText(0, i, 0, str3D, Color(1.0, 1.0, 1.0), _fontSize);
	}
	for (int i = _stepY; i < _halfY; i += _stepY)
	{
		char str3D[1024];
		sprintf_s(str3D, "%g", (i / (float)_stepY) * _incY);
		renderingContext->RenderText(0, i, 0, str3D, Color(1.0, 1.0, 1.0), _fontSize);
	}
	for (int i = -_stepX; i > -_halfX; i -= _stepX)
	{
		char str3D[1024];
		sprintf_s(str3D, "%g", (i / (float)_stepX) * _incX);
		renderingContext->RenderText(i, 0, 0, str3D, Color(1.0, 1.0, 1.0), _fontSize);
	}
	for (int i = _stepX; i < _halfX; i += _stepX)
	{
		char str3D[1024];
		sprintf_s(str3D, "%g", (i / (float)_stepX) * _incX);
		renderingContext->RenderText(i, 0, 0, str3D, Color(1.0, 1.0, 1.0), _fontSize);
	}
	for (int i = -_stepZ; i > -_halfZ; i -= _stepZ)
	{
		char str3D[1024];
		sprintf_s(str3D, "%g", (i / (float)_stepZ) * _incZ);
		renderingContext->RenderText(0, 0, i, str3D, Color(1.0, 1.0, 1.0), _fontSize);
	}
	for (int i = _stepZ; i < _halfZ; i += _stepZ)
	{
		char str3D[1024];
		sprintf_s(str3D, "%g", (i / (float)_stepZ) * _incZ);
		renderingContext->RenderText(0, 0, i, str3D, Color(1.0, 1.0, 1.0), _fontSize);
	}
	renderingContext->RenderText(0, 0, 0, "0", Color(1.0, 1.0, 1.0), _fontSize);

	OnMathRender();

	glBegin(GL_LINES);
	glColor3d(1.0, 1.0, 1.0);
	glVertex3d((double)-_halfX, 0.0, 0.0);
	glVertex3d((double)_halfX, 0.0, 0.0);
	glVertex3d(0.0, (double)-_halfY, 0.0);
	glVertex3d(0.0, (double)_halfY, 0.0);
	glEnd();
	
	glBegin(GL_LINES);
	glColor3d(0.1, 0.1, 0.1);
	for (int i = -_stepY; i > -_halfY; i -= _stepY)
	{
		glVertex3d((double)-_halfX, i, 0.0);
		glVertex3d((double)_halfX, i, 0.0);
				 
		glVertex3d(0.0, i, (double)-_halfZ);
		glVertex3d(0.0, i, (double)_halfZ);
	}
	for (int i = _stepY; i < _halfY; i += _stepY)
	{
		glVertex3d((double)-_halfX, i, 0.0);
		glVertex3d((double)_halfX, i, 0.0);
				 
		glVertex3d(0.0, i, (double)-_halfZ);
		glVertex3d(0.0, i, (double)_halfZ);
	}
	for (int i = -_stepX; i > -_halfX; i -= _stepX)
	{
		glVertex3d(i, (double)-_halfY, 0.0);
		glVertex3d(i, (double)_halfY, 0.0);

		glVertex3d(i, 0.0, (double)-_halfZ);
		glVertex3d(i, 0.0, (double)_halfZ);
	}
	for (int i = _stepX; i < _halfX; i += _stepX)
	{
		glVertex3d(i, (double)-_halfY, 0.0);
		glVertex3d(i, (double)_halfY, 0.0);

		glVertex3d(i, 0.0, (double)-_halfZ);
		glVertex3d(i, 0.0, (double)_halfZ);
	}
	for (int i = -_stepZ; i > -_halfZ; i -= _stepZ)
	{
		glVertex3d(0.0, (double)-_halfY, i);
		glVertex3d(0.0, (double)_halfY, i);

		glVertex3d((double)-_halfX, 0.0, i);
		glVertex3d((double)_halfX, 0.0, i);
	}
	for (int i = _stepZ; i < _halfZ; i += _stepZ)
	{
		glVertex3d(0.0, (double)-_halfY, i);
		glVertex3d(0.0, (double)_halfY, i);

		glVertex3d((double)-_halfX, 0.0, i);
		glVertex3d((double)_halfX, 0.0, i);
	}
	glEnd();
}

void GLMath3DApplication::OnMathRender()
{

}

void GLMath3DApplication::Shutdown()
{
	GLApplication::Shutdown();
}

void GLMath3DApplication::OnResize(int width, int height)
{
	GLApplication::OnResize(width, height);

	_halfY = (int)((height / 2.0) * 20);
	_halfX = (int)((width / 2.0) * 20);
	_halfZ = (int)((width / 2.0) * 20);
	_stepX = 40;
	_stepY = 40;
	_stepZ = 40;

	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, width / float(height), 1, 10000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void GLMath3DApplication::OnMouseWheel(int distance, int x, int y)
{
	bool scaleGraph = false;
	double scaleValue = _defInc;
	if ((GetKeyState(VK_LSHIFT) & 0x80) || (GetKeyState(VK_LCONTROL) & 0x80))
		scaleGraph = true;

	if ((GetKeyState(VK_LSHIFT) & 0x80) && (GetKeyState(VK_LCONTROL) & 0x80))
		scaleValue *= 100.0;
	else if (GetKeyState(VK_LCONTROL) & 0x80)
		scaleValue *= 10.0;

	if (scaleGraph)
	{
		if (distance > 1)
		{
			_incX += scaleValue;
			_incY += scaleValue;
			_incZ += scaleValue;
		}
		else
		{
			_incX -= scaleValue;
			_incY -= scaleValue;
			_incZ -= scaleValue;
		}

		if (_incX <= scaleValue)
			_incX = scaleValue;
		if (_incY <= scaleValue)
			_incY = scaleValue;
		if (_incZ <= scaleValue)
			_incZ = scaleValue;
	}
	else
		GLApplication::OnMouseWheel(distance, x, y);
}
